using Circus.CodeEditor;
using Circus.Syntax;
using Circus.Syntax.Lexer;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace Circus.CodeEditor.TextSource {
    [DesignerCategory("Code"), ToolboxBitmap(typeof(CodeEditor), "Images.TextSource.bmp")]
    public class TextSource : Component, INotifier {


        [Category("TextSource"), Description("Occurs when spelling of some word within the text needs checking.")]
        public event WordSpellEvent WordSpell;



        protected class StorePos {
            public Point Point;
            public bool EndPos;
            public StorePos(Point point, bool endPos) {
                this.Point = point;
                this.EndPos = endPos;
            }
        }
        public class BackgroundThread {
            private IList<ThreadProcsEventArgs> actions = new List<ThreadProcsEventArgs>();
            private TextSource owner;
            private Thread thread;
            public BackgroundThread(TextSource owner) {
                this.owner = owner;
            }
            protected void Execute(ThreadProcsEventArgs action) {
                if (!action.Aborted) {
                    if (action.Start != null) {
                        if (this.owner.ActiveEdit != null && this.owner.ActiveEdit.IsHandleCreated) {
                            this.owner.ActiveEdit.Invoke(action.Start);
                        } else {
                            action.Start();
                        }
                    }
                    if (!action.Aborted) {
                        action.Action();
                        if (!action.Aborted) {
                            if (action.End != null) {
                                if (this.owner.ActiveEdit != null && this.owner.ActiveEdit.IsHandleCreated) {
                                    this.owner.ActiveEdit.Invoke(action.End);
                                } else {
                                    action.End();
                                }
                            }
                        }
                    }
                }
            }
            protected void Resume() {
                ThreadProcsEventArgs threadProcsEventArgs = null;
                IList<ThreadProcsEventArgs> obj;
                Monitor.Enter(obj = this.actions);
                try {
                    threadProcsEventArgs = ((this.actions.Count > 0) ? this.actions[0] : null);
                } finally {
                    Monitor.Exit(obj);
                }
                threadProcsEventArgs.Aborted = false;
                bool flag = false;
                while (!flag && threadProcsEventArgs != null) {
                    this.Execute(threadProcsEventArgs);
                    flag = threadProcsEventArgs.Aborted;
                    Monitor.Enter(obj = this.actions);
                    try {
                        this.actions.Remove(threadProcsEventArgs);
                        threadProcsEventArgs = ((this.actions.Count > 0) ? this.actions[0] : null);
                    } finally {
                        Monitor.Exit(obj);
                    }
                }
            }
            protected void AddAction(ThreadProcsEventArgs action) {
                IList<ThreadProcsEventArgs> obj;
                Monitor.Enter(obj = this.actions);
                try {
                    for (int i = 0; i < this.actions.Count; i++) {
                        if (this.actions[i].Action == action.Action) {
                            return;
                        }
                    }
                    this.actions.Add(action);
                } finally {
                    Monitor.Exit(obj);
                }
            }
            public void Run() {
                if (this.thread == null || !this.thread.IsAlive) {
                    this.thread = new Thread(new ThreadStart(this.Resume));
                    this.thread.Start();
                }
            }
            public void Start(ThreadProcsEventArgs action) {
                this.AddAction(action);
                this.Run();
            }
            public void Stop(ThreadProc proc, bool wait) {
                bool flag = false;
                IList<ThreadProcsEventArgs> obj;
                Monitor.Enter(obj = this.actions);
                try {
                    ThreadProcsEventArgs threadProcsEventArgs = (this.actions.Count > 0) ? this.actions[0] : null;
                    if (threadProcsEventArgs != null && threadProcsEventArgs.Action == proc) {
                        if (threadProcsEventArgs.Stop != null) {
                            threadProcsEventArgs.Stop();
                        }
                        threadProcsEventArgs.Aborted = true;
                        flag = wait;
                    } else {
                        for (int i = this.actions.Count - 1; i > 0; i--) {
                            if (this.actions[i].Action == proc) {
                                this.actions.RemoveAt(i);
                                break;
                            }
                        }
                    }
                } finally {
                    Monitor.Exit(obj);
                }
                if (this.thread != null && this.thread.IsAlive && flag) {
                    this.thread.Join(EditConsts.DefaultThreadWaitTimeout);
                }
            }
        }
        private class ErrComparer : IComparer<SyntaxError> {
            public int Compare(SyntaxError x, SyntaxError y) {
                Point position = x.Position;
                Point position2 = y.Position;
                int num = position.Y - position2.Y;
                if (num == 0) {
                    num = position.X - position2.X;
                }
                return num;
            }
        }
        protected class TrackChange {
            public int Line;
            public bool Saved;
            public TrackChange(int line, bool saved) {
                this.Line = line;
                this.Saved = saved;
            }
        }
        protected class TrackChangeComparer : IComparer {
            public int Compare(object x, object y) {
                return ((TextSource.TrackChange)x).Line - (int)y;
            }
        }
        private CodeSnippetRanges codeSnippets;
        private CodeSnippetRange currentSnippet;
        private int snippetUpdateCount;
        private IComparer<SyntaxError> errComparer;
        private SyntaxErrors syntaxErrors;
        private bool readOnly;
        private static bool overWrite;
        private bool modified;
        private int stringsUpdateCount;
        private bool singleLineMode;
        private IndentOptions indentOptions = EditConsts.DefaultIndentOptions;

        private bool globalSearch = false;
        private Point position;
        private Point prevPosition;
        private NavigateOptions navigateOptions = EditConsts.DefaultNavigateOptions;
        private int updatePositionCount = 0;
        private UndoList undoList;
        private UndoList redoList;
        private UndoOptions undoOptions = EditConsts.DefaultUndoOptions;
        private int saveModifiedIdx = -1;
        private int undoLimitDelta = 16;
        private bool redo;
        private int undoUpdateCount;
        private int lockUndoCount;
        private Hashtable trackChanges;
        private IComparer trackChangeComparer;
        private List<TextSource.StorePos> positionList;
        private int updateCount;
        private NotifyState state;
        private int firstChanged = -1;
        private int lastChanged = -1;
        private int lastParsed = -1;
        private int firstUpdated = -1;
        private int lastUpdated = -1;
        private Rectangle selectBlockRect;
        private int count;
        private UndoFlags undoFlag;
        private UpdateReason reason;
        private bool needFormatting;
        private bool needFmtTimer;
        private bool highlightHyperText;
        private HyperTextEventArgs hyperTextArgs;
        private Hashtable urlTable;
        private bool checkSpelling;
        private WordSpellEventArgs wordSpellArgs;
        private Point spellSkipPt = new Point(-1, -1);
        private Hashtable spellTable;
        private char[] spellDelimiters = EditConsts.DefaultSpellDelimiters.ToCharArray();
        private Point openBrace = new Point(-1, -1);
        private Point closingBrace = new Point(-1, -1);
        private int openBraceLen = 1;
        private int closingBraceLen = 1;
        private char[] openBraces = EditConsts.DefaultOpenBraces;
        private char[] closingBraces = EditConsts.DefaultClosingBraces;
        private Braces.BracesList bracesList;
        private Rectangle[] tempBraceRects = null;
        private System.Windows.Forms.Timer bracesTimer;
        private BracesOptions bracesOptions;
        private Circus.Syntax.Lexer.Lexer lexer;
        private ThreadProc reparseTextAction;
        private ThreadProc reparseTextStart;
        private ThreadProc reparseTextEnd;
        private ThreadProc reparseTextStop;
        private IList<Rectangle> undefinedSections = null;
        private int parserLine = 0;
        private string fileName = string.Empty;
        private CodeEditor activeEdit;
        private TextStrings lines;
        private IList<CodeEditor> edits;
        private LineStyles lineStyles;
        private BookMarks bookMarks;
        private System.Windows.Forms.Timer fmtTimer;
        private TextSource.BackgroundThread thread;
        private Hashtable threads;

        [Category("TextSource"), Description("Occurs when undo/redo operation performed.")]
        public event UndoEvent UndoEvent;

        private event EventHandler notifyHandler;

        [Category("TextSource"), Description("Occurs when a control needs checking whether some string represents hypertext.")]
        public event HyperTextEvent HyperText;

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual CodeSnippetRanges CodeSnippets {
            get {
                return this.codeSnippets;
            }
            set {
                this.BeginUpdate(UpdateReason.Other);
                try {
                    this.UnhighlightCodeSnippets(false);
                    foreach (CodeSnippetRange current in value) {
                        this.codeSnippets.Add(current);
                    }
                    this.HighlightCodeSnippets(false);
                } finally {
                    this.EndUpdate();
                }
            }
        }
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual CodeSnippetRange CurrentSnippet {
            get {
                return this.currentSnippet;
            }
            set {
                if (this.currentSnippet != value) {
                    if (this.currentSnippet != null) {
                        int num = this.codeSnippets.IndexOf(this.currentSnippet);
                        if (num >= 0 && this.CodeSnippets.IsFirstSnippet(num)) {
                            this.UpdateSnippetValues(this.currentSnippet);
                        }
                    }
                    this.currentSnippet = value;
                    this.InvalidateSnippets();
                }
            }
        }
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public SyntaxErrors SyntaxErrors {
            get {
                return this.syntaxErrors;
            }
        }

        protected bool AllowUndo {
            get {
                return (this.undoOptions & UndoOptions.AllowUndo) != UndoOptions.None;
            }
        }
        protected bool GroupUndo {
            get {
                return (this.undoOptions & UndoOptions.GroupUndo) != UndoOptions.None;
            }
        }
        protected bool UndoNavigations {
            get {
                return (this.undoOptions & UndoOptions.UndoNavigations) != UndoOptions.None;
            }
        }

        [Category("Behavior"), DefaultValue(false), Description("Gets or sets a value indicating whether the control's content is read-only.")]
        public virtual bool ReadOnly {
            get {
                return this.readOnly;
            }
            set {
                if (this.readOnly != value) {
                    this.readOnly = value;
                    this.OnReadOnlyChanged();
                }
            }
        }
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual bool Overwrite {
            get {
                return TextSource.overWrite;
            }
            set {
                if (TextSource.overWrite != value) {
                    TextSource.overWrite = value;
                    this.BeginUpdate(UpdateReason.Other);
                    try {
                        this.State |= (this.State | NotifyState.OverWriteChanged);
                    } finally {
                        this.EndUpdate();
                    }
                }
            }
        }
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual bool Modified {
            get {
                return this.modified;
            }
            set {
                if (this.modified != value) {
                    this.modified = value;
                    this.OnModifiedChanged();
                }
            }
        }
        [Category("Behavior"), DefaultValue(false), Description("Gets or sets a value indicating whether the control accepts only one line of the text.")]
        public virtual bool SingleLineMode {
            get {
                return this.singleLineMode;
            }
            set {
                if (this.singleLineMode != value) {
                    this.singleLineMode = value;
                    this.OnSingleLineModeChanged();
                }
            }
        }
        [Category("Behavior"), Description("Gets or sets \"QWhale.Editor.TextSource.IndentOptions\" for this class, allowing to customize behaior of Edit control when user presses Enter to insert new text line."), Editor("QWhale.Design.FlagEnumerationEditor, QWhale.Design", typeof(UITypeEditor))]
        public virtual IndentOptions IndentOptions {
            get {
                return this.indentOptions;
            }
            set {
                if (this.indentOptions != value) {
                    this.indentOptions = value;
                    this.OnIndentOptionsChanged();
                }
            }
        }


        [Category("Behavior"), Description("Gets or sets navigating options."), Editor("QWhale.Design.FlagEnumerationEditor, QWhale.Design", typeof(UITypeEditor))]
        public virtual NavigateOptions NavigateOptions {
            get {
                return this.navigateOptions;
            }
            set {
                if (this.navigateOptions != value) {
                    this.navigateOptions = value;
                    this.OnNavigateOptionsChanged();
                }
            }
        }
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual Point PrevPosition {
            get {
                return this.prevPosition;
            }
        }
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual Point Position {
            get {
                return this.position;
            }
            set {
                this.MoveTo(value.X, value.Y);
            }
        }
        [Category("Behavior"), Description("Gets or sets options for undo and redo operations."), Editor("QWhale.Design.FlagEnumerationEditor, QWhale.Design", typeof(UITypeEditor))]
        public virtual UndoOptions UndoOptions {
            get {
                return this.undoOptions;
            }
            set {
                if (this.undoOptions != value) {
                    if (((this.undoOptions ^ value) & UndoOptions.AllowUndo) != UndoOptions.None) {
                        this.ClearUndo();
                        this.ClearRedo();
                    }
                    this.undoOptions = value;
                    this.OnUndoOptionsChanged();
                }
            }
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual int UpdateCount {
            get {
                return this.updateCount;
            }
        }
        protected int SnippetUpdateCount {
            get {
                return this.snippetUpdateCount;
            }
            set {
                this.snippetUpdateCount = value;
            }
        }
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual Rectangle SelectBlockRect {
            get {
                return this.selectBlockRect;
            }
        }
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual NotifyState State {
            get {
                return this.state;
            }
            set {
                if (this.state != value) {
                    this.state = value;
                    this.OnStateChanged();
                }
            }
        }
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual int FirstChanged {
            get {
                return this.firstChanged;
            }
        }
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual int LastChanged {
            get {
                return this.lastChanged;
            }
        }
        [Browsable(false), DefaultValue("\r\n"), Description("Gets or sets a string value that terminates line."), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual string LineTerminator {
            get {
                return this.lines.LineTerminator;
            }
            set {
                if (this.lines != null) {
                    this.lines.LineTerminator = value;
                }
            }
        }
        [Category("Behavior"), DefaultValue(false), Description("Gets or sets a value indicating whether hypertext urls in the text should be highlighted.")]
        public virtual bool HighlightHyperText {
            get {
                return this.highlightHyperText;
            }
            set {
                if (this.highlightHyperText != value) {
                    this.highlightHyperText = value;
                    this.OnHighlightHyperTextChanged();
                }
            }
        }
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Hashtable UrlTable {
            get {
                return this.urlTable;
            }
        }

        #region Spelling
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual Hashtable SpellTable {
            get {
                return this.spellTable;
            }
        }
        [Category("Behavior"), DefaultValue(false), Description("Gets or sets a value indicating whether the document can check spelling for its content.")]
        public virtual bool CheckSpelling {
            get {
                return this.checkSpelling;
            }
            set {
                if (this.checkSpelling != value) {
                    this.checkSpelling = value;
                    this.OnCheckSpellingChanged();
                }
            }
        }
        [Browsable(false), Description("Gets or sets an array of chars used to separate words in a text when performing spelling check."), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual char[] SpellDelimiters {
            get {
                return this.spellDelimiters;
            }
            set {
                if (this.spellDelimiters != value) {
                    this.spellDelimiters = value;
                    this.OnSpellDelimitersChanged();
                }
            }
        }
        [Browsable(false), Description("Gets or sets \"SpellDelimiters\" as a single string."), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual string SpellDelimiterString {
            get {
                return new string(this.SpellDelimiters);
            }
            set {
                this.SpellDelimiters = value.ToCharArray();
            }
        }
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual bool HasSpelling {
            get {
                return this.WordSpell != null;
            }
        }
        #endregion

        protected Rectangle[] TempBraceRects {
            get {
                return this.tempBraceRects;
            }
            set {
                if (this.tempBraceRects != value) {
                    this.UpdateTempBraces(false, true);
                    this.tempBraceRects = value;
                    this.UpdateTempBraces(true, true);
                    if (value != null) {
                        this.StartBracesTimer();
                    }
                }
            }
        }
        [Category("Braces"), DefaultValue(BracesOptions.None), Description("Gets or sets options specifying appearance and behaviour of matching braces within Edit control."), Editor("QWhale.Design.FlagEnumerationEditor, QWhale.Design", typeof(UITypeEditor))]
        public virtual BracesOptions BracesOptions {
            get {
                return this.bracesOptions;
            }
            set {
                if (this.bracesOptions != value) {
                    this.bracesOptions = value;
                    this.OnBracesOptionsChanged();
                }
            }
        }
        [Category("Braces"), Description("Gets or sets an array of characters each one representing an open brace.")]
        public virtual char[] OpenBraces {
            get {
                return this.openBraces;
            }
            set {
                this.openBraces = value;
                this.OnOpenBracesChanged();
            }
        }
        [Category("Braces"), Description("Gets or sets an array of characters each one representing a closing brace.")]
        public virtual char[] ClosingBraces {
            get {
                return this.closingBraces;
            }
            set {
                this.closingBraces = value;
                this.OnClosingBracesChanged();
            }
        }
        protected Rectangle[] UndefinedSections {
            set {
                if ((value != null && value.Length != 0) || (this.undefinedSections != null && this.undefinedSections.Count != 0)) {
                    this.UpdateUndefinedSections(false, false);
                    if (value == null) {
                        if (this.undefinedSections != null) {
                            this.undefinedSections.Clear();
                        }
                    } else {
                        if (this.undefinedSections == null) {
                            this.undefinedSections = new List<Rectangle>();
                        }
                        this.undefinedSections.Clear();
                        for (int i = 0; i < value.Length; i++) {
                            Rectangle item = value[i];
                            this.undefinedSections.Add(item);
                        }
                    }
                    this.UpdateUndefinedSections(true, false);
                }
            }
        }
        [Category("TextSource"), Description("Gets or sets text source content in the form of string array."), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), TypeConverter(typeof(CollectionConverter))]
        public virtual string[] Strings {
            get {
                string[] array = new string[this.lines.Count];
                for (int i = 0; i < this.lines.Count; i++) {
                    array[i] = this.lines[i];
                }
                return array;
            }
            set {
                this.lines.BeginUpdate();
                try {
                    this.lines.Clear();
                    for (int i = 0; i < value.Length; i++) {
                        string item = value[i];
                        this.lines.Add(item);
                    }
                } finally {
                    this.lines.EndUpdate();
                }
            }
        }
        [Category("TextSource"), Description("Gets or sets object that can perform lexical analysis of the text source content.")]
        public virtual Circus.Syntax.Lexer.Lexer Lexer {
            get {
                return this.lexer;
            }
            set {
                if (this.lexer != value) {
                    if (this.lexer != null) {
                        this.lexer.RemoveNotifier(this);
                    }
                    this.lexer = value;
                    if (this.lexer != null) {
                        this.lexer.AddNotifier(this);
                    }
                    if (this.lexer is SyntaxParser) {
                        ((SyntaxParser)this.lexer).Prepare(this.fileName, this.Lines, null, false);
                    }
                    this.LexerChanged();
                }
            }
        }

        [Category("TextSource"), DefaultValue(""), Description("Gets or sets name of file that holds text source content.")]
        public virtual string FileName {
            get {
                return this.fileName;
            }
            set {
                if (this.fileName != value) {
                    this.fileName = value;
                }
            }
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual TextStrings Lines {
            get {
                return this.lines;
            }
            set {
                if (this.lines != value) {
                    this.lines = value;
                    this.OnLinesChanged();
                }
            }
        }

        [Description("Gets or sets text source content as a single string with the individual strings delimited by carriage returns.")]
        public virtual string Text {
            get {
                return this.Lines.Text;
            }
            set {
                if (this.Lines != null && this.Lines.Text != value) {
                    this.Lines.Text = value;
                    this.OnTextChanged();
                }
            }
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual LineStyles LineStyles {
            get {
                return this.lineStyles;
            }
            set {
                if (this.lineStyles != value) {
                    this.lineStyles = value;
                    this.OnLineStylesChanged();
                }
            }
        }
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual BookMarks BookMarks {
            get {
                return this.bookMarks;
            }
            set {
                if (this.bookMarks != value) {
                    this.bookMarks = value;
                    this.OnBookmarksChanged();
                }
            }
        }
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual CodeEditor ActiveEdit {
            get {
                return this.activeEdit;
            }
            set {
                if (this.activeEdit != value) {
                    this.activeEdit = value;
                    this.OnActiveEditChanged();
                }
            }
        }

        public TextSource() {
            StringItemInfo colorStyle = default(StringItemInfo);
            colorStyle.Data = 255;
            this.positionList = new List<TextSource.StorePos>();
            this.lines = this.CreateTextStrings();
            this.undoList = new UndoList();
            this.redoList = new UndoList();
            this.edits = new List<CodeEditor>();
            this.threads = new Hashtable();
            this.lineStyles = this.CreateLineStyles();
            this.bookMarks = this.CreateBookMarks();
            this.syntaxErrors = this.CreateSyntaxErrors();
            this.codeSnippets = this.CreateCodeSnippets();
            this.errComparer = new TextSource.ErrComparer();
            this.bracesList = new Braces.BracesList();
            this.trackChangeComparer = new TextSource.TrackChangeComparer();
            this.hyperTextArgs = new HyperTextEventArgs("", false);
            this.wordSpellArgs = new WordSpellEventArgs("", true, colorStyle);
            this.reparseTextAction = new ThreadProc(this.ReparseTextAction);
            this.reparseTextStart = new ThreadProc(this.ReparseTextStart);
            this.reparseTextEnd = new ThreadProc(this.ReparseTextEnd);
            this.reparseTextStop = new ThreadProc(this.ReparseTextStop);
            BookMarkManager.Register(this);
        }
        private string GetSnippetValue(CodeSnippetRange range) {
            string text = this.Lines[range.StartPoint.Y];
            string result;
            if (range.StartPoint.X >= 0 && range.StartPoint.X < text.Length) {
                if (range.EndPoint.Y == range.StartPoint.Y) {
                    result = ((range.StartPoint.X <= range.EndPoint.X) ? text.Substring(range.StartPoint.X, Math.Min(range.EndPoint.X, text.Length) - range.StartPoint.X) : string.Empty);
                } else {
                    result = text.Substring(range.StartPoint.X);
                }
            } else {
                result = string.Empty;
            }
            return result;
        }
        private void SetSnippetValue(CodeSnippetRange range, string value) {
            this.BeginUpdate(UpdateReason.Insert);
            try {
                this.MoveTo(range.StartPoint);
                this.DeleteRight((range.EndPoint.Y == range.StartPoint.Y) ? (range.EndPoint.X - range.StartPoint.X) : int.MaxValue);
                this.Insert(value);
            } finally {
                this.EndUpdate();
            }
        }
        private void UpdateSnippetValues(CodeSnippetRange snippet) {
            int index = this.StorePosition(this.Position);
            this.BeginUpdate(UpdateReason.Insert);
            try {
                string snippetValue = this.GetSnippetValue(snippet);
                for (int i = this.codeSnippets.Count - 1; i >= 0; i--) {
                    CodeSnippetRange codeSnippetRange = this.codeSnippets[i];
                    if (codeSnippetRange != snippet && codeSnippetRange.ID == snippet.ID) {
                        if (this.GetSnippetValue(codeSnippetRange) != snippetValue) {
                            this.SetSnippetValue(codeSnippetRange, snippetValue);
                        }
                    }
                }
            } finally {
                this.Position = this.RestorePosition(index);
                this.EndUpdate();
            }
        }
        private void InvalidateSnippets() {
            if (this.codeSnippets.Count > 0) {
                this.BeginUpdate(UpdateReason.Other);
                try {
                    this.LinesChanged(this.codeSnippets[0].StartPoint.Y, this.codeSnippets[this.codeSnippets.Count - 1].EndPoint.Y, false);
                    this.state |= NotifyState.BlockChanged;
                } finally {
                    this.EndUpdate();
                }
            }
        }
        protected bool IsFirstSnippet(Point position) {
            int index;
            return this.codeSnippets.FindSnippet(position, false, out index) && this.codeSnippets.IsFirstSnippet(index);
        }
        protected virtual void HighlightCodeSnippets(bool needUpdate) {
            for (int i = 0; i < this.codeSnippets.Count; i++) {
                if (this.codeSnippets.IsFirstSnippet(i)) {
                    Range range = this.codeSnippets[i];
                    this.SetTextStyle(new Rectangle(range.StartPoint, new Size(range.EndPoint.X - range.StartPoint.X, range.EndPoint.Y - range.StartPoint.Y)), TextStyle.CodeSnippet, true, needUpdate);
                }
            }
        }
        protected virtual void UnhighlightCodeSnippets(bool needUpdate) {
            foreach (Range current in this.codeSnippets) {
                this.SetTextStyle(new Rectangle(current.StartPoint, new Size(current.EndPoint.X - current.StartPoint.X, current.EndPoint.Y - current.StartPoint.Y)), TextStyle.CodeSnippet, false, needUpdate);
            }
            this.codeSnippets.Clear();
        }
        protected virtual TextStrings CreateTextStrings() {
            TextStrings textStrings = new TextStrings(this);
            textStrings.AddNotifier(this);
            return textStrings;
        }
        protected virtual LineStyles CreateLineStyles() {
            return new LineStyles(this);
        }
        protected virtual BookMarks CreateBookMarks() {
            return new BookMarks(this);
        }
        protected virtual SyntaxErrors CreateSyntaxErrors() {
            return new SyntaxErrors();
        }
        protected virtual CodeSnippetRanges CreateCodeSnippets() {
            return new CodeSnippetRanges();
        }
        public virtual CodeSnippetRange GetCodeSnippetRangeAt(Point position) {
            int index;
            return this.codeSnippets.FindSnippet(position, false, out index) ? this.codeSnippets[index] : null;
        }

        public virtual void UnhighlightCodeSnippets() {
            this.UnhighlightCodeSnippets(true);
        }
        public virtual int BeginUpdateSnippet() {
            this.snippetUpdateCount++;
            return this.SnippetUpdateCount;
        }
        public virtual int EndUpdateSnippet() {
            this.snippetUpdateCount--;
            return this.snippetUpdateCount;
        }
        protected virtual TextStyle GetErrorStyle(SyntaxError err) {
            TextStyle result;
            switch (err.ErrorType) {
                case SyntaxErrorType.Error:
                    result = TextStyle.WaveLine;
                    break;
                case SyntaxErrorType.Warning:
                    result = TextStyle.WaveLine;
                    break;
                case SyntaxErrorType.Info:
                    result = TextStyle.WaveLine;
                    break;
                default:
                    throw new ArgumentOutOfRangeException("err", "ErrorType is unknown.");
            }
            return result;
        }
        protected virtual void UnhighlightSyntaxErrors(SyntaxErrors errors, int line, bool needUpdate) {
            for (int i = errors.Count - 1; i >= 0; i--) {
                SyntaxError syntaxError = errors[i];
                if (syntaxError.Position.Y == line) {
                    this.SetTextStyle(new Rectangle(syntaxError.Position, syntaxError.Size), this.GetErrorStyle(syntaxError), false, needUpdate);
                    errors.RemoveAt(i);
                }
            }
        }
        protected virtual void UnhighlightSyntaxErrors(SyntaxErrors errors, bool needUpdate) {
            foreach (SyntaxError current in errors) {
                this.SetTextStyle(new Rectangle(current.Position, current.Size), this.GetErrorStyle(current), false, needUpdate);
            }
        }
        public void InvalidateSyntaxErrors() {
            foreach (SyntaxError current in this.syntaxErrors) {
                this.SetTextStyle(new Rectangle(current.Position, current.Size), this.GetErrorStyle(current), true, true);
            }
        }
        public void HighlightSyntaxErrors() {
            SyntaxParser syntaxParser = this.Lexer as SyntaxParser;
            SyntaxErrors syntaxErrors = new SyntaxErrors();
            syntaxParser.GetSyntaxErrors(syntaxErrors);
            syntaxErrors.Sort(this.errComparer);
            foreach (SyntaxError current in syntaxErrors) {
                int index;
                if (this.syntaxErrors.FindErrorAt(current.Position, true, out index, this.errComparer) && this.syntaxErrors[index].Range.EndPoint.Equals(current.Range.EndPoint)) {
                    this.syntaxErrors.RemoveAt(index);
                }
            }
            this.BeginUpdate(UpdateReason.Other);
            try {
                if (syntaxErrors.Count > 0) {
                    this.ParseToString(Math.Min(syntaxErrors[syntaxErrors.Count - 1].Position.Y, this.lines.Count - 1));
                }
                this.UnhighlightSyntaxErrors(this.syntaxErrors, false);
                this.syntaxErrors.Clear();
                foreach (SyntaxError current in syntaxErrors) {
                    this.syntaxErrors.Add((SyntaxError)current.Clone());
                }
                foreach (SyntaxError current in this.syntaxErrors) {
                    this.SetTextStyle(new Rectangle(current.Position, current.Size), this.GetErrorStyle(current), true, true);
                }
            } finally {
                this.EndUpdate();
            }
        }
        public void UnhighlightSyntaxErrors() {
            this.UnhighlightSyntaxErrors(this.syntaxErrors, true);
        }
        public virtual SyntaxError GetSyntaxErrorAt(int x, int y) {
            int index;
            return this.syntaxErrors.FindErrorAt(new Point(x, y), false, out index, this.errComparer) ? this.syntaxErrors[index] : null;
        }

        private bool GetModified(UndoList list, int index) {
            index = list.UndoCount - Math.Max(0, index);
            bool result;
            for (int i = list.Count - 1; i >= 0; i--) {
                UndoData undoData = list[i];
                if (undoData.Operation != UndoOperation.Navigate || undoData.Data != null) {
                    index--;
                    if (index < 0) {
                        break;
                    }
                }
                if (undoData.Operation != UndoOperation.Navigate && undoData.Operation != UndoOperation.NavigateEx && undoData.Operation != UndoOperation.UndoBlock) {
                    result = true;
                    return result;
                }
            }
            result = false;
            return result;
        }
        private void EnsurePosInsideText() {
            if (this.position.Y >= this.lines.Count) {
                while (this.position.Y >= this.lines.Count) {
                    this.lines.Add(string.Empty);
                }
                this.LinesChanged(this.position.Y, int.MaxValue, false);
            }
        }
        private bool GetPrevIndent(out string indent) {
            indent = string.Empty;
            string text = this.Lines[this.position.Y];
            bool result;
            if (text.Trim() != string.Empty) {
                int num = text.Length - text.TrimStart(null).Length;
                if (this.position.X <= num) {
                    if ((this.indentOptions & IndentOptions.UsePrevIndent) != IndentOptions.None) {
                        indent = text.Substring(0, this.position.X);
                    } else {
                        indent = this.lines.GetIndentString(this.Lines.TabPosToPos(text, this.position.X), 0);
                    }
                    result = true;
                    return result;
                }
            }
            result = false;
            return result;
        }
        private string GetPrevIndentStr(out int indent) {
            indent = 0;
            string result;
            for (int i = this.position.Y - 1; i >= 0; i--) {
                string text = this.Lines[i];
                if (text.Trim() != string.Empty) {
                    int num = text.Length - text.TrimStart(null).Length;
                    indent = this.Lines.TabPosToPos(text, num);
                    result = text.Substring(0, num);
                    return result;
                }
            }
            result = string.Empty;
            return result;
        }
        private int GetTabIndent(int indent) {
            return this.lines.TabPosToPos(new string('\t', indent), indent);
        }
        private string GetAutoIndent() {
            string result;
            if ((this.indentOptions & IndentOptions.AutoIndent) != IndentOptions.None) {
                if ((this.indentOptions & IndentOptions.SmartIndent) != IndentOptions.None && this.NeedFormatText()) {
                    string text = ((SyntaxParser)this.lexer).GetSmartIndentString(this.Position.Y, true, this.lines.UseSpaces, this.lines.GetTabStop(0));
                    if (text == null) {
                        int num = Math.Max(((SyntaxParser)this.lexer).GetSmartIndent(this.Position.Y, true), 0);
                        text = this.lines.GetIndentString(this.lines.UseSpaces ? num : this.GetTabIndent(num), 0);
                    }
                    result = text;
                } else {
                    int num = 0;
                    string text2 = string.Empty;
                    text2 = this.GetPrevIndentStr(out num);
                    if ((this.indentOptions & IndentOptions.UsePrevIndent) != IndentOptions.None) {
                        result = text2;
                    } else {
                        result = this.lines.GetIndentString(num, 0);
                    }
                }
            } else {
                result = string.Empty;
            }
            return result;
        }
        protected virtual void OnSingleLineModeChanged() {
            if (this.singleLineMode && this.lines.Count > 1) {
                this.DeleteBlock(new Rectangle(0, 1, 0, this.lines.Count - 1));
                this.MoveToLine(0);
            }
        }
        protected virtual void OnReadOnlyChanged() {
            this.BeginUpdate(UpdateReason.Other);
            try {
                this.State |= NotifyState.ReadOnlyChanged;
            } finally {
                this.EndUpdate();
            }
        }

        protected virtual void OnModifiedChanged() {
            this.BeginUpdate(UpdateReason.Other);
            try {
                this.ModifiedChanged();
            } finally {
                this.EndUpdate();
            }
        }
        protected virtual void OnIndentOptionsChanged() {
        }
        protected virtual void OnMaxLengthChanged() {
        }

        protected void ModifiedChanged() {
            if (!this.modified) {
                if (true) {
                    for (int i = 0; i < this.undoList.Count; i++) {
                        UndoData expr_30 = this.undoList[i];
                        expr_30.UndoFlag |= UndoFlags.Saved;
                    }
                    for (int i = 0; i < this.redoList.Count; i++) {
                        UndoData expr_65 = this.redoList[i];
                        expr_65.UndoFlag &= ~UndoFlags.Saved;
                    }
                    this.saveModifiedIdx = this.GetUndoList().UndoCount - 1;
                } else {
                    this.ClearUndo();
                    this.ClearRedo();
                }
            }
            this.state |= NotifyState.ModifiedChanged;
        }
        protected bool LexStateChanged(int line) {
            bool result;
            if (this.lexer != null && line >= 0 && line < this.lines.Count) {
                int lexState = this.lines.GetItem(line).LexState;
                int num = (line > 0 && line - 1 < this.lines.Count) ? this.lines.GetItem(line - 1).LexState : this.lexer.DefaultState;
                StringItem item = this.lines.GetItem(line);
                result = (this.ParseText(num, item, line, true) != lexState);
            } else {
                result = false;
            }
            return result;
        }
        protected int ParseText(int state, StringItem item, int line, bool parseTextOnly) {
            this.parserLine = line;
            int result = state;
            if (this.lexer != null) {
                StringItemInfo[] textData = item.TextData;
                result = this.lexer.ParseText(state, line, item.String, ref textData);
                item.TextData = textData;
            }
            if (!parseTextOnly) {
                if (this.highlightHyperText) {
                    this.DoHighlightUrls(item);
                }
                if (this.checkSpelling && this.WordSpell != null) {
                    this.DoCheckSpelling(item, line, false);
                }
                if (this.bracesOptions != BracesOptions.None) {
                    this.DoParseBraces(item, line);
                }
            }
            return result;
        }
        protected void StringsChanged(object sender, EventArgs ea) {
            if (this.stringsUpdateCount == 0) {
                this.BeginUpdate(UpdateReason.Other);
                try {
                    this.ClearUndo();
                    this.ClearRedo();
                    int num = ((TextStrings)sender).FirstChanged;
                    int num2 = ((TextStrings)sender).LastChanged;
                    this.BlockDeleting(new Rectangle(0, num, 0, num2));
                    this.modified = false;
                    this.LinesChanged(num, num2);
                    this.State |= (this.State | NotifyState.Edit | NotifyState.PositionChanged | NotifyState.ModifiedChanged | NotifyState.CountChanged | NotifyState.StringsChanged);
                    this.PositionChanged(UpdateReason.Other, 0, 0);
                    this.UpdateParsed(num, num2);
                    if ((this.navigateOptions & NavigateOptions.KeepCaret) == NavigateOptions.None) {
                        this.MoveToLine(Math.Max(Math.Min(num, this.lines.Count - 1), 0));
                    } else {
                        if (this.Position.Y >= this.lines.Count - 1) {
                            this.MoveToLine(Math.Max(this.lines.Count - 1, 0));
                        }
                    }
                } finally {
                    this.EndUpdate();
                }
            }
        }
        protected virtual void BlockDeleting(Point pt, int len) {
            if (this.updatePositionCount <= 0) {
                if (pt.X == 0 && this.lines[pt.Y] == string.Empty) {
                    len = int.MaxValue;
                }
                Rectangle rect = new Rectangle(pt.X, pt.Y, len, 0);
                if (this.bookMarks.BlockDeleting(rect)) {
                    this.state |= NotifyState.BookMarkChanged;
                }
                if (this.lineStyles.BlockDeleting(rect)) {
                    this.state |= NotifyState.BookMarkChanged;
                }
                if (this.UndefinedSectionsDeleting(rect)) {
                    this.State |= NotifyState.BookMarkChanged;
                }
                if (this.codeSnippets.BlockDeleting(rect)) {
                    this.state |= NotifyState.BlockChanged;
                }
            }
        }
        protected virtual void BlockDeleting(Rectangle rect) {
            if ((rect.X == 0 || rect.Height > 0) && this.lines.GetLength(rect.Bottom) <= rect.Width) {
                rect.Width = int.MaxValue;
            }
            this.bracesList.BlockDeleting(rect);
            this.syntaxErrors.BlockDeleting(rect);
            this.codeSnippets.BlockDeleting(rect);
            if (this.snippetUpdateCount == 0 && this.codeSnippets.NeedClear(rect)) {
                this.UnhighlightCodeSnippets(false);
            }
            if (this.bookMarks.BlockDeleting(rect)) {
                this.state |= NotifyState.BookMarkChanged;
            }
            if (this.lineStyles.BlockDeleting(rect)) {
                this.state |= NotifyState.BookMarkChanged;
            }
            if (this.UndefinedSectionsDeleting(rect)) {
                this.State |= NotifyState.BookMarkChanged;
            }
            if (this.lexer is SyntaxParser && ((SyntaxParser)this.lexer).Options != SyntaxOptions.None) {
                ((SyntaxParser)this.lexer).BlockDeleting(rect);
            }
        }
        protected void IndentLine(string indent) {
            if (indent != string.Empty) {
                if ((this.indentOptions & IndentOptions.JumpToIndent) != IndentOptions.None) {
                    NavigateOptions navigateOptions = this.navigateOptions;
                    try {
                        this.navigateOptions |= NavigateOptions.BeyondEol;
                        this.Navigate(this.lines.TabPosToPos(indent, indent.Length), 0);
                    } finally {
                        this.navigateOptions = navigateOptions;
                    }
                } else {
                    this.Insert(indent);
                }
            }
        }
        protected virtual void PositionChanged(UpdateReason reason, int deltaX, int deltaY) {
            if (this.updatePositionCount <= 0) {
                if (this.notifyHandler != null) {
                    this.notifyHandler(this, new PositionChangedEventArgs(reason, deltaX, deltaY));
                }
                this.bracesList.PositionChanged(this.Position.X, this.Position.Y, deltaX, deltaY);
                this.syntaxErrors.PositionChanged(this.Position.X, this.Position.Y, deltaX, deltaY);
                this.codeSnippets.PositionChanged(this.Position.X, this.Position.Y, deltaX, deltaY, (this.state & NotifyState.SmartFormat) != NotifyState.None);
                this.UndefinedSectionChanged(deltaX, deltaY);
                if (this.snippetUpdateCount == 0 && this.codeSnippets.NeedClear(this.Position.Y)) {
                    this.UnhighlightCodeSnippets(false);
                }
                if (this.bookMarks.PositionChanged(this.Position.X, this.Position.Y, deltaX, deltaY)) {
                    this.state |= NotifyState.BookMarkChanged;
                }
                if (this.lineStyles.PositionChanged(this.Position.X, this.Position.Y, deltaX, deltaY)) {
                    this.state |= NotifyState.BookMarkChanged;
                }
                if (this.lexer is SyntaxParser && ((SyntaxParser)this.lexer).Options != SyntaxOptions.None) {
                    ((SyntaxParser)this.lexer).PositionChanged(this.Position.X, this.Position.Y, deltaX, deltaY);
                }
                for (int i = 0; i < this.positionList.Count; i++) {
                    TextSource.StorePos storePos = this.positionList[i];
                    Range.UpdatePos(this.Position.X, this.Position.Y, deltaX, deltaY, ref storePos.Point, storePos.EndPos);
                }
            }
        }

        public virtual bool Insert(string text) {
            bool result;
            if (this.readOnly) {
                result = false;
            } else {
                this.BeginUpdate(UpdateReason.Insert);
                this.stringsUpdateCount++;
                try {
                    this.EnsurePosInsideText();
                    string text2 = this.lines[this.position.Y];
                    int length = text2.Length;
                    if (this.position.X > length) {
                        text = this.lines.GetIndentString(this.position.X - length, this.Lines.TabPosToPos(text2, length)) + text;
                        this.MoveTo(length, this.position.Y);
                    }
                    this.lines[this.position.Y] = text2.Insert(this.position.X, text);
                    length = text.Length;
                    this.AddUndo(UndoOperation.Insert, length);
                    if (this.LexStateChanged(this.position.Y)) {
                        this.LinesChanged(this.position.Y, int.MaxValue, true);
                    } else {
                        this.LinesChanged(this.position.Y, this.position.Y, true);
                    }
                    this.PositionChanged(UpdateReason.Insert, length, 0);
                    if (!this.UndoNavigations || (this.state & NotifyState.Undo) == NotifyState.None) {
                        if ((this.state & NotifyState.Undo) != NotifyState.None) {
                            this.DisableUndo();
                            try {
                                this.Navigate(length, 0);
                            } finally {
                                this.EnableUndo();
                            }
                        } else {
                            this.Navigate(length, 0);
                        }
                    }
                } finally {
                    this.stringsUpdateCount--;
                    this.EndUpdate();
                }
                result = true;
            }
            return result;
        }

        public virtual bool DeleteRight(int len) {
            bool result;
            if (this.readOnly || false || len <= 0 || this.position.Y >= this.lines.Count || this.position.X >= this.lines.GetLength(this.position.Y)) {
                result = false;
            } else {
                this.BeginUpdate(UpdateReason.Delete);
                this.stringsUpdateCount++;
                try {
                    string text = this.lines[this.position.Y];
                    len = Math.Min(len, text.Length - this.position.X);
                    this.AddUndo(UndoOperation.Delete, text.Substring(this.position.X, len));
                    text = text.Remove(this.position.X, len);
                    this.lines[this.position.Y] = text;
                    this.BlockDeleting(this.position, len);
                    if (this.LexStateChanged(this.position.Y)) {
                        this.LinesChanged(this.position.Y, int.MaxValue, true);
                    } else {
                        this.LinesChanged(this.position.Y, this.position.Y, true);
                    }
                    this.PositionChanged(UpdateReason.Delete, -len, 0);
                } finally {
                    this.stringsUpdateCount--;
                    this.EndUpdate();
                }
                result = true;
            }
            return result;
        }
        public virtual bool DeleteLeft(int len) {
            bool result;
            if (this.readOnly) {
                result = false;
            } else {
                this.BeginUpdate(UpdateReason.Delete);
                try {
                    len = Math.Min(len, this.position.X);
                    this.Navigate(-len, 0);
                    result = this.DeleteRight(len);
                } finally {
                    this.EndUpdate();
                }
            }
            return result;
        }
        public virtual bool InsertBlock(string text) {
            return this.InsertBlock(StringItem.Split(text));
        }
        public virtual bool InsertBlock(string[] strings) {
            return this.InsertBlock(strings, false);
        }
        public virtual bool InsertBlock(TextStrings strings) {
            bool result;
            if (!this.readOnly) {
                string[] array = new string[strings.Count];
                strings.CopyTo(array, 0);
                result = this.InsertBlock(array);
            } else {
                result = false;
            }
            return result;
        }
        public virtual bool InsertBlock(string[] strings, bool select) {
            bool result;
            if (this.readOnly || false || strings.Length == 0) {
                result = false;
            } else {
                if (this.singleLineMode) {
                    strings = new string[]
					{
						strings[0]
					};
                }

                this.BeginUpdate(UpdateReason.InsertBlock);
                this.stringsUpdateCount++;
                try {
                    Point location = this.Position;
                    this.EnsurePosInsideText();
                    string text = this.lines[this.position.Y];
                    int num = text.Length;
                    string str = string.Empty;
                    if (this.position.X > num) {
                        strings[0] = this.lines.GetIndentString(this.position.X - num, this.Lines.TabPosToPos(text, num)) + strings[0];
                        this.MoveTo(num, this.position.Y);
                    }
                    num = 0;
                    string[] array = strings;
                    for (int i = 0; i < array.Length; i++) {
                        string text2 = array[i];
                        num += text2.Length + 2;
                    }
                    num -= 2;
                    this.AddUndo(UndoOperation.InsertBlock, new Point(num, strings.Length - 1));
                    for (int j = 0; j < strings.Length; j++) {
                        if (j == 0) {
                            string text2 = this.lines[this.position.Y];
                            num = text2.Length;
                            if (this.position.X < num) {
                                str = text2.Substring(this.position.X, num - this.Position.X);
                                text2 = text2.Substring(0, this.position.X) + strings[0];
                            } else {
                                text2 += strings[0];
                            }
                            if (j == strings.Length - 1) {
                                text2 += str;
                            }
                            this.lines[this.position.Y] = text2;
                        } else {
                            if (j == strings.Length - 1) {
                                this.lines.Insert(this.position.Y + j, strings[j] + str);
                            } else {
                                this.lines.Insert(this.position.Y + j, strings[j]);
                            }
                        }
                    }
                    this.LinesChanged(this.position.Y, int.MaxValue, true);
                    int num2 = strings.Length - 1;
                    int num3 = strings[strings.Length - 1].Length;
                    if (num2 > 0) {
                        num3 -= this.Position.X;
                    }
                    this.PositionChanged(UpdateReason.InsertBlock, num3, num2);
                    if (!this.UndoNavigations || (this.state & NotifyState.Undo) == NotifyState.None) {
                        this.Navigate(num3, num2);
                    }
                    if (select) {
                        this.state |= NotifyState.SelectBlock;
                        this.selectBlockRect = new Rectangle(location, new Size(this.position.X - location.X, this.position.Y - location.Y));
                    }
                } finally {
                    this.stringsUpdateCount--;
                    this.EndUpdate();
                }
                result = true;
            }
            return result;
        }
        public virtual bool DeleteBlock(int len) {
            Point point = this.IncPosition(this.position, len);
            return this.DeleteBlock(new Rectangle(this.position.X, this.position.Y, point.X - this.position.X, point.Y - this.position.Y));
        }
        public virtual bool DeleteBlock(Rectangle rect) {
            bool result;
            if (this.readOnly) {
                result = false;
            } else {
                rect.Height = Math.Min(rect.Bottom, this.lines.Count) - rect.Top;
                if (rect.Height < 0) {
                    result = false;
                } else {
                    this.BeginUpdate(UpdateReason.DeleteBlock);
                    this.stringsUpdateCount++;
                    try {
                        this.BlockDeleting(rect);
                        if (this.notifyHandler != null) {
                            this.notifyHandler(this, new BlockDeletingEventArgs(rect));
                        }
                        this.MoveTo(rect.Left, rect.Top);
                        string text = this.lines[rect.Top];
                        int num = text.Length;
                        int num2 = rect.Left - num;
                        if (rect.Top == rect.Bottom && num2 > 0) {
                            result = false;
                            return result;
                        }
                        int num3 = rect.Bottom;
                        if (num3 == this.lines.Count) {
                            num3--;
                        }
                        string[] array = new string[num3 - rect.Top + 1];
                        this.AddUndo(UndoOperation.DeleteBlock, array);
                        for (int i = rect.Bottom - 1; i > rect.Top; i--) {
                            array[i - rect.Top] = this.lines[i];
                            this.lines.RemoveAt(i);
                        }
                        if (rect.Left < num) {
                            if (rect.Top == rect.Bottom) {
                                num = Math.Min(rect.Right, num) - rect.Left;
                            } else {
                                num = text.Length - rect.Left;
                            }
                            if (array.Length > 0) {
                                array[0] = text.Substring(rect.Left, num);
                            }
                            if (rect.Top < this.lines.Count) {
                                this.lines[rect.Top] = text.Remove(rect.Left, num);
                            }
                        } else {
                            if (array.Length > 0) {
                                array[0] = string.Empty;
                            }
                        }
                        if (rect.Top != rect.Bottom) {
                            text = this.lines[rect.Top + 1];
                            num = Math.Min(text.Length, rect.Right);
                            if (rect.Bottom - rect.Top < array.Length) {
                                array[rect.Bottom - rect.Top] = text.Substring(0, num);
                            }
                            if (rect.Top < this.lines.Count) {
                                this.lines[rect.Top] = this.lines[rect.Top] + ((num2 > 0) ? new string(' ', num2) : string.Empty) + text.Remove(0, num);
                                if (rect.Top + 1 < this.lines.Count) {
                                    this.lines.RemoveAt(rect.Top + 1);
                                }
                            }
                        }
                        this.PositionChanged(UpdateReason.DeleteBlock, -(rect.Right - rect.Left), -(rect.Bottom - rect.Top));
                        this.LinesChanged(rect.Top, int.MaxValue, true);
                    } finally {
                        this.stringsUpdateCount--;
                        this.EndUpdate();
                    }
                    result = true;
                }
            }
            return result;
        }
        public virtual bool BreakLine() {
            bool result;
            if (this.readOnly) {
                result = false;
            } else {

                if (this.position.Y == 0 && this.lines.Count == 0) {
                    this.lines.Add(string.Empty);
                }
                if (this.singleLineMode) {
                    result = false;
                } else {
                    if (this.position.Y >= this.lines.Count) {
                        if ((NavigateOptions.BeyondEof & this.navigateOptions) == NavigateOptions.None) {
                            result = false;
                            return result;
                        }
                        this.EnsurePosInsideText();
                    }
                    this.BeginUpdate(UpdateReason.Break);
                    this.stringsUpdateCount++;
                    try {
                        string text = this.lines[this.position.Y];
                        int length = text.Length;
                        if (this.position.X < length) {
                            this.lines.Insert(this.position.Y + 1, text.Substring(this.position.X, length - this.position.X));
                            this.lines[this.position.Y] = text.Substring(0, this.position.X);
                        } else {
                            this.lines.Insert(this.position.Y + 1, string.Empty);
                        }
                        this.AddUndo(UndoOperation.Break, null);
                        this.LinesChanged(this.position.Y, int.MaxValue, true);
                        this.PositionChanged(UpdateReason.Break, -this.position.X, 1);
                        if ((this.state & NotifyState.Undo) == NotifyState.None) { }
                    } finally {
                        this.stringsUpdateCount--;
                        this.EndUpdate();
                    }
                    result = true;
                }
            }
            return result;
        }
        public virtual bool UnBreakLine() {
            bool result;
            int index = this.position.Y + 1;
            if (this.readOnly || this.position.Y >= this.lines.Count - 1 || this.lines.Count <= 1 || false || false) {
                result = false;
            } else {
                string text = this.lines[this.position.Y];
                if ((this.state & NotifyState.Undo) != NotifyState.None) {
                    if (this.position.X + 1 < text.Length && this.position.X + 1 >= text.TrimEnd(new char[0]).Length) {
                        text = text.Substring(0, this.position.X);
                    }
                }
                int num = text.Length;
                if (this.position.X + 1 >= num) {
                    this.BeginUpdate(UpdateReason.UnBreak);
                    this.stringsUpdateCount++;
                    try {
                        num = this.position.X - num;
                        if (num >= 0 && this.lines[this.position.Y + 1] != string.Empty) {
                            this.lines[this.position.Y] = text + new string(' ', num) + this.lines[this.position.Y + 1];
                        } else {
                            this.lines[this.position.Y] = text + this.lines[this.position.Y + 1];
                        }
                        this.lines.RemoveAt(this.position.Y + 1);
                        this.AddUndo(UndoOperation.UnBreak, null);
                        this.LinesChanged(this.position.Y, int.MaxValue, true);
                        this.PositionChanged(UpdateReason.UnBreak, this.position.X, -1);
                    } finally {
                        this.stringsUpdateCount--;
                        this.EndUpdate();
                    }
                    result = true;
                } else {
                    result = false;
                }
            }
            return result;
        }
        public virtual bool NewLine() {
            bool result;
            if (this.singleLineMode) {
                result = false;
            } else {
                this.BeginUpdate(UpdateReason.Break);
                try {
                    string indent;
                    bool prevIndent = this.GetPrevIndent(out indent);
                    bool flag = this.BreakLine();
                    this.MoveTo(0, this.Position.Y + 1);
                    if (prevIndent) {
                        this.IndentLine(indent);
                    } else {
                        this.IndentLine();
                    }
                    result = flag;
                } finally {
                    this.EndUpdate();
                }
            }
            return result;
        }
        public virtual void IndentLine() {
            this.IndentLine(this.GetAutoIndent());
        }
        public virtual bool NewLineAbove() {
            bool result;
            if (this.singleLineMode) {
                result = false;
            } else {
                this.BeginUpdate(UpdateReason.Break);
                try {
                    this.MoveToChar(0);
                    bool flag = this.BreakLine();
                    string autoIndent = this.GetAutoIndent();
                    if (autoIndent != string.Empty) {
                        this.Insert(autoIndent);
                    }
                    result = flag;
                } finally {
                    this.EndUpdate();
                }
            }
            return result;
        }
        public virtual bool NewLineBelow() {
            bool result;
            if (this.singleLineMode) {
                result = false;
            } else {
                this.BeginUpdate(UpdateReason.Break);
                try {
                    this.MoveToChar(this.Lines[this.Position.Y].Length);
                    bool flag = this.BreakLine();
                    this.MoveTo(0, this.Position.Y + 1);
                    string autoIndent = this.GetAutoIndent();
                    if (autoIndent != string.Empty) {
                        this.Insert(autoIndent);
                    }
                    result = flag;
                } finally {
                    this.EndUpdate();
                }
            }
            return result;
        }

        protected virtual void OnNavigateOptionsChanged() {
            this.ValidatePosition(ref this.position);
        }

        public virtual void Navigate(int deltaX, int deltaY) {
            if (deltaX != 0 || deltaY != 0) {
                this.BeginUpdate(UpdateReason.Navigate);
                try {
                    if (deltaY != 0) {
                        bool addUndo = (NavigateOptions.BeyondEof & this.navigateOptions) == NavigateOptions.None;
                    }
                    Point point = this.position;
                    this.position.Offset(deltaX, deltaY);
                    this.ValidatePosition(ref this.position);
                    if (this.UndoNavigations) {
                        this.AddUndo(UndoOperation.Navigate, new Point(this.position.X - point.X, this.position.Y - point.Y));
                    } else {
                        this.AddUndo(UndoOperation.Navigate, null);
                    }
                } finally {
                    this.EndUpdate();
                }
            }
        }
        public virtual void MoveTo(int x, int y) {
            this.Navigate(x - this.position.X, y - this.position.Y);
        }
        public virtual void MoveTo(Point position) {
            this.MoveTo(position.X, position.Y);
        }
        public virtual void MoveToChar(int x) {
            this.Navigate(x - this.position.X, 0);
        }
        public virtual void MoveToLine(int y) {
            this.Navigate(0, y - this.position.Y);
        }
        public virtual void MoveToLine(int y, int linesAbove) {
            this.BeginUpdate();
            try {
                this.MoveToLine(y);
                if (this.activeEdit != null) {
                    this.activeEdit.Scrolling.WindowOriginY = Math.Max(y - linesAbove, 0);
                }
            } finally {
                this.EndUpdate();
            }
        }
        public virtual void ValidatePosition(ref Point position) {
            if (position.Y < 0) {
                position.Y = 0;
            }
            if (position.X < 0) {
                position.X = 0;
            }
            if (((NavigateOptions.BeyondEof & this.navigateOptions) == NavigateOptions.None || this.singleLineMode) && position.Y >= this.lines.Count) {
                position.Y = Math.Max(this.lines.Count - 1, 0);
            }
            if ((NavigateOptions.BeyondEol & this.navigateOptions) == NavigateOptions.None) {
                int num = (position.Y < this.lines.Count) ? this.lines.GetLength(position.Y) : 0;
                if (position.X >= num) {
                    position.X = num;
                }
            }
        }
        public virtual int StorePosition(Point position) {
            return this.StorePosition(position, false);
        }
        public virtual int StorePosition(Point position, bool endPos) {
            this.positionList.Add(new TextSource.StorePos(position, endPos));
            return this.positionList.Count - 1;
        }
        public virtual Point RestorePosition(int index) {
            Point point;
            if (index < this.positionList.Count) {
                point = this.positionList[index].Point;
                this.positionList.RemoveAt(index);
            } else {
                point = new Point(0, 0);
            }
            return point;
        }
        public virtual int StorePositionWithUndo(Point position) {
            if ((this.UndoOptions & UndoOptions.UndoNavigations) == UndoOptions.None) {
                this.AddUndo(UndoOperation.NavigateEx, null);
            }
            return this.StorePosition(position);
        }
        public virtual void RestorePositionWithUndo(int index) {
            this.Position = this.RestorePosition(index);
            if ((this.UndoOptions & UndoOptions.UndoNavigations) == UndoOptions.None) {
                this.AddUndo(UndoOperation.NavigateEx, null);
            }
        }
        public virtual void DisablePositionUpdate() {
            this.updatePositionCount++;
        }
        public virtual void EnablePositionUpdate() {
            this.updatePositionCount--;
        }

        public virtual void SetNavigateOptions(NavigateOptions navigateOptions) {
            this.navigateOptions = navigateOptions;
        }
      
        private bool SkipNavigations(UndoList list) {
            if (list.Count != 0) {
                UndoData undoData = list[list.Count - 1];
                if (undoData.Operation == UndoOperation.Navigate && undoData.Data == null) {
                    this.BeginUpdate(UpdateReason.Navigate);
                    try {
                        while (list.Count > 0) {
                            undoData = list[list.Count - 1];
                            if (undoData.Operation != UndoOperation.Navigate || undoData.Data != null) {
                                break;
                            }
                            this.Undo(undoData);
                            list.RemoveAt(list.Count - 1);
                        }
                    } finally {
                        this.EndUpdate();
                    }
                }
            }
            return list.Count == 0;
        }
        private bool FindTrackChange(SortList<TextSource.TrackChange> list, int line, out int idx) {
            return list.FindLast(line, out idx, this.trackChangeComparer);
        }
        private void AddTrackChange(SortList<TextSource.TrackChange> list, int line, bool saved) {
            int index;
            if (this.FindTrackChange(list, line, out index)) {
                list[index].Saved &= saved;
            } else {
                list.Insert(index, new TextSource.TrackChange(line, saved));
            }
        }
        protected UndoList GetUndoList() {
            UndoList result;
            if (this.redo) {
                result = this.redoList;
            } else {
                result = this.undoList;
            }
            return result;
        }
        protected bool IsEmptyUndoList(UndoList list) {
            bool result;
            if (this.UndoNavigations) {
                result = (list.Count == 0);
            } else {
                for (int i = list.Count - 1; i >= 0; i--) {
                    UndoData undoData = list[i];
                    if (undoData.Operation != UndoOperation.Navigate) {
                        result = false;
                        return result;
                    }
                }
                result = true;
            }
            return result;
        }
        protected int TrackChanges(UndoList uList, SortList<TextSource.TrackChange> list) {
            int num = -1;
            for (int i = 0; i < uList.Count; i++) {
                UndoData undoData = uList[i];
                int y = undoData.Position.Y;
                int num2 = 0;
                bool flag = true;
                switch (undoData.Operation) {
                    case UndoOperation.Insert:
                    case UndoOperation.Delete:
                        num2 = 0;
                        break;
                    case UndoOperation.Break:
                        num2 = 1;
                        break;
                    case UndoOperation.UnBreak:
                        num2 = -1;
                        break;
                    case UndoOperation.InsertBlock:
                        num2 = ((Point)undoData.Data).Y;
                        break;
                    case UndoOperation.DeleteBlock:
                        num2 = -((string[])undoData.Data).Length + 1;
                        break;
                    default:
                        flag = false;
                        break;
                }
                if (flag) {
                    bool flag2 = (byte)(undoData.UndoFlag & UndoFlags.Saved) != 0;
                    if (flag2) {
                        num++;
                    }
                    if (num2 != 0) {
                        for (int j = list.Count - 1; j >= 0; j--) {
                            TextSource.TrackChange trackChange = list[j];
                            if (trackChange.Line < y) {
                                break;
                            }
                            if (trackChange.Line + num2 < y) {
                                flag2 &= trackChange.Saved;
                                list.RemoveAt(j);
                            } else {
                                trackChange.Line += num2;
                            }
                        }
                    }
                    for (int j = 0; j <= Math.Max(num2, 0); j++) {
                        this.AddTrackChange(list, y + j, flag2);
                    }
                }
            }
            return num;
        }
        protected void TrackChanges() {
            this.trackChanges = new Hashtable();
            SortList<TextSource.TrackChange> sortList = new SortList<TextSource.TrackChange>();
            this.TrackChanges(this.undoList, sortList);
            foreach (TextSource.TrackChange current in sortList) {
                this.trackChanges[current.Line] = current.Saved;
            }
            sortList.Clear();
        }
        protected void ClearTrackChanges() {
            if (this.trackChanges != null) {
                this.trackChanges.Clear();
            }
            this.trackChanges = null;
        }
        protected virtual void OnUndoOptionsChanged() {
        }

        public virtual void AddUndo(UndoOperation operation, object data) {
            if (this.AllowUndo && this.undoUpdateCount == 0) {
                UndoData undoData = new UndoData(operation, data);
                undoData.Position = this.position;
                undoData.Reason = this.reason;
                undoData.UpdateCount = this.lockUndoCount;
                undoData.UndoFlag = this.undoFlag;
                this.GetUndoList().Add(undoData);
                this.undoFlag = UndoFlags.None;
            }
        }
        public virtual void Undo() {
            UndoList undoList = this.GetUndoList();
            undoList.BeginUpdate();
            try {
                if (this.AllowUndo && undoList.Count > 0 && !this.readOnly) {
                    this.redo = !this.redo;
                    try {
                        if (!this.SkipNavigations(undoList)) {
                            UndoData undoData = undoList[undoList.Count - 1];
                            UpdateReason updateReason = undoData.Reason;
                            bool flag = undoData.Operation == UndoOperation.UndoBlock;
                            this.BeginUpdate(updateReason);
                            try {
                                this.state |= NotifyState.Undo;
                                while (undoList.Count > 0) {
                                    undoData = undoList[undoList.Count - 1];
                                    int num = undoData.UpdateCount;
                                    if (updateReason != undoData.Reason && num == 0) {
                                        break;
                                    }
                                    bool flag2 = (byte)(undoData.UndoFlag & UndoFlags.FirstTime) != 0;
                                    UndoOperation operation = undoData.Operation;
                                    if (operation == UndoOperation.UndoBlock && !flag) {
                                        break;
                                    }
                                    this.Undo(undoData);
                                    undoList.RemoveAt(undoList.Count - 1);
                                    if (flag2 && ((!this.GroupUndo && num <= 0) || ((this.undoOptions & UndoOptions.UngroupBreaks) != UndoOptions.None && (updateReason == UpdateReason.Break || updateReason == UpdateReason.UnBreak)))) {
                                        break;
                                    }
                                }
                            } finally {
                                this.EndUpdate();
                            }
                        }
                    } finally {
                        this.redo = !this.redo;
                    }
                }
            } finally {
                undoList.EndUpdate();
            }
        }
        public virtual void Undo(UndoData undoData) {
            if (!this.UndoNavigations && (undoData.Operation <= UndoOperation.DeleteBlock || undoData.Operation == UndoOperation.NavigateEx)) {
                this.position = undoData.Position;
            }
            this.undoFlag = (((byte)(undoData.UndoFlag & UndoFlags.Saved) != 0) ? (this.undoFlag | UndoFlags.Saved) : (this.undoFlag & ~UndoFlags.Saved));
            switch (undoData.Operation) {
                case UndoOperation.Insert:
                    this.DeleteRight((int)undoData.Data);
                    break;
                case UndoOperation.Delete:
                    this.Insert((string)undoData.Data);
                    break;
                case UndoOperation.Break:
                    this.UnBreakLine();
                    break;
                case UndoOperation.UnBreak:
                    this.BreakLine();
                    break;
                case UndoOperation.InsertBlock:
                    this.DeleteBlock(((Point)undoData.Data).X);
                    break;
                case UndoOperation.DeleteBlock:
                    this.InsertBlock((string[])undoData.Data, this.reason == UpdateReason.Delete || this.reason == UpdateReason.DeleteBlock);
                    break;
                case UndoOperation.Navigate:
                    if (undoData.Data != null) {
                        this.Navigate(-((Point)undoData.Data).X, -((Point)undoData.Data).Y);
                    } else {
                        this.AddUndo(UndoOperation.Navigate, null);
                    }
                    break;
                case UndoOperation.NavigateEx:
                    this.AddUndo(UndoOperation.NavigateEx, undoData.Data);
                    break;
            }
            if (this.UndoEvent != null) {
                this.UndoEvent(this, new UndoEventArgs(undoData));
            }
        }
        public virtual void Redo() {
            this.redo = !this.redo;
            try {
                this.Undo();
            } finally {
                this.redo = !this.redo;
            }
        }
        public virtual bool CanUndo() {
            return this.AllowUndo && !this.IsEmptyUndoList(this.undoList);
        }
        public virtual bool CanRedo() {
            return this.AllowUndo && !this.IsEmptyUndoList(this.redoList);
        }
        public virtual void ClearUndo() {
            this.undoList.Clear();
        }
        public void ClearRedo() {
            this.redoList.Clear();
            if (this.saveModifiedIdx >= this.undoList.UndoCount) {
                this.saveModifiedIdx = -1;
            }
        }
        public virtual int DisableUndo() {
            this.undoUpdateCount++;
            return this.undoUpdateCount;
        }
        public virtual int EnableUndo() {
            this.undoUpdateCount--;
            return this.undoUpdateCount;
        }

        public virtual bool LineIsModified(int index) {
            bool flag = false;
            return this.LineIsModified(index, out flag);
        }
        public virtual bool LineIsModified(int index, out bool saved) {
            if (this.trackChanges == null) {
                this.TrackChanges();
            }
            object obj = this.trackChanges[index];
            saved = (obj != null && (bool)obj);
            return obj != null;
        }

        public virtual int BeginUpdate() {
            return this.BeginUpdate(UpdateReason.Other);
        }
        public virtual int EndUpdate() {
            this.updateCount--;
            if (this.updateCount == 0) {
                if (this.position != this.prevPosition) {
                    this.state |= NotifyState.PositionChanged;
                }
                if ((this.state & NotifyState.Edit) != NotifyState.None) {
                    if (!this.modified) {
                        this.state |= NotifyState.ModifiedChanged;
                    }
                    this.modified = true;
                    if (this.firstChanged >= 0) {
                        this.lastParsed = Math.Min(this.lastParsed, this.firstChanged);
                    }
                }
                if ((this.state & NotifyState.Edit) != NotifyState.None || (this.state & NotifyState.ModifiedChanged) != NotifyState.None) {
                    this.ClearTrackChanges();
                }
                if (this.lines.Count != this.count) {
                    this.state |= NotifyState.CountChanged;
                }
                if ((this.state & NotifyState.Undo) == NotifyState.None && ((this.state & NotifyState.Edit) != NotifyState.None || ((this.state & NotifyState.PositionChanged) != NotifyState.None && this.UndoNavigations))) {
                    this.ClearRedo();
                }
                bool flag = (this.state & NotifyState.PositionChanged) != NotifyState.None && (this.state & NotifyState.Edit) == NotifyState.None;
                if (this.state != NotifyState.None) {
                    bool flag2 = this.modified;
                    if (true) {
                        if (this.undoList.UndoCount > this.saveModifiedIdx) {
                            this.modified = this.GetModified(this.undoList, this.saveModifiedIdx + 1);
                        } else {
                            this.modified = this.GetModified(this.redoList, this.redoList.UndoCount + this.undoList.UndoCount - (this.saveModifiedIdx + 1));
                        }
                    } else {
                        this.modified = this.GetModified(this.undoList, 0);
                    }
                    if (flag2 != this.modified) {
                        this.state |= NotifyState.ModifiedChanged;
                    }
                    bool flag3 = this.needFmtTimer || (this.state & NotifyState.Edit) != NotifyState.None || (this.state & NotifyState.SyntaxChanged) != NotifyState.None || (this.state & NotifyState.StringsChanged) != NotifyState.None;
                    bool flag4 = this.position.Y != this.prevPosition.Y || (this.state & NotifyState.CountChanged) != NotifyState.None;
                    if (flag3 || flag4) {
                        this.updateCount++;
                        try {
                            this.StartFmtTimer(flag3, flag4);
                        } finally {
                            this.updateCount--;
                        }
                    }
                    this.needFmtTimer = false;
                    this.Update();
                }
                if (this.bracesOptions != BracesOptions.None && flag) {
                    this.HighlightBraces();
                }
                if (this.checkSpelling && (this.state & NotifyState.PositionChanged) != NotifyState.None && this.spellSkipPt.Y >= 0 && this.spellSkipPt.X >= 0 && this.spellSkipPt.Y == this.prevPosition.Y && this.prevPosition.Y != this.position.Y) {
                    StringItem item = this.lines.GetItem(this.prevPosition.Y);
                    if (item != null) {
                        this.DoCheckSpelling(item, this.prevPosition.Y, true);
                    }
                }
            }
            return this.updateCount;
        }

        public virtual void AddNotifier(INotifier sender) {
            this.notifyHandler = (EventHandler)Delegate.Combine(this.notifyHandler, new EventHandler(sender.Notification));
        }
        public virtual void RemoveNotifier(INotifier sender) {
            this.notifyHandler = (EventHandler)Delegate.Remove(this.notifyHandler, new EventHandler(sender.Notification));
        }
        public virtual void Update() {
            if (this.updateCount == 0) {
                this.Notify(EventArgs.Empty);
            }
        }
        public virtual void Notify(EventArgs e) {
            if (this.notifyHandler != null) {
                this.notifyHandler(this, e);
            }
        }
        protected virtual void OnStateChanged() {
        }
        public virtual int BeginUpdate(UpdateReason reason) {
            if (this.updateCount == 0) {
                this.firstChanged = -1;
                this.lastChanged = -1;
                if (reason != UpdateReason.Other && reason != UpdateReason.Navigate) {
                    if (this.bracesOptions != BracesOptions.None) {
                        this.UnhighlightBraces(false);
                    }
                    this.UnhighlightSyntaxErrors(this.syntaxErrors, this.position.Y, false);
                    this.needFmtTimer = (this.fmtTimer != null && this.fmtTimer.Enabled);
                    this.EndFmtTimer(true);
                }
                if (reason != UpdateReason.Other) {
                    this.TempUnhighlightBraces(false);
                }
                this.state = NotifyState.None;
                this.prevPosition = this.position;
                this.selectBlockRect = Rectangle.Empty;
                this.reason = reason;
                this.undoFlag = UndoFlags.FirstTime;
                this.count = this.lines.Count;
            }
            this.updateCount++;
            return this.updateCount;
        }
        public virtual void LinesChanged(int first, int last) {
            this.LinesChanged(first, last, false);
        }
        public virtual void LinesChanged(int first, int last, bool modified) {
            if (this.firstChanged == -1) {
                this.firstChanged = first;
            } else {
                this.firstChanged = Math.Min(this.firstChanged, first);
            }
            this.lastChanged = Math.Max(this.lastChanged, last);
            if (modified) {
                this.state |= (NotifyState.Edit | NotifyState.Modified);
            }
        }
        public virtual void Notification(object sender, EventArgs e) {
            if (sender is TextStrings) {
                this.StringsChanged(sender, e);
            } else {
                if (sender is Circus.Syntax.Lexer.Lexer) {
                    if (e is SyntaxParserEventArgs) {
                        this.SyntaxParserChanged(e);
                    } else {
                        if (e is CodeCompletionArgs) {
                            this.Notify(e);
                        } else {
                            this.LexerChanged();
                        }
                    }
                }
            }
        }

        private void InitUrlTable() {
            if (this.urlTable == null) {
                this.urlTable = new Hashtable();
                for (char c = 'A'; c <= 'Z'; c += '\u0001') {
                    this.urlTable.Add(c, true);
                }
                for (char c = 'a'; c <= 'z'; c += '\u0001') {
                    this.urlTable.Add(c, true);
                }
                for (char c = '0'; c <= '9'; c += '\u0001') {
                    this.urlTable.Add(c, false);
                }
                char[] array = EditConsts.DefaultUrlChars.ToCharArray();
                for (int i = 0; i < array.Length; i++) {
                    char c = array[i];
                    this.urlTable.Add(c, false);
                }
            }
        }
        private void DoCheckSpelling(StringItem item, int line, int start, int end, bool withUpdate) {
            if (start != end) {
                if (!this.IsWordCorrect(item.String.Substring(start, end - start), item.TextData[start])) {
                    item.SetTextStyle(start, end - start, TextStyle.MisSpelledWord | TextStyle.WaveLine);
                    if (withUpdate) {
                        this.LinesChanged(line, line);
                        this.state |= NotifyState.BlockChanged;
                    }
                }
            }
        }
        protected void DoHighlightUrls(StringItem item) {
            string @string = item.String;
            int length = @string.Length;
            int i = 0;
            this.InitUrlTable();
            while (i < length) {
                int num = i;
                while (i < length) {
                    object obj = this.urlTable[@string[i]];
                    if (obj != null && (bool)obj) {
                        break;
                    }
                    i++;
                }
                int num2 = i;
                while (num2 < length && this.urlTable.ContainsKey(@string[num2])) {
                    num2++;
                }
                if (num2 != i && this.IsHyperText(@string.Substring(i, num2 - i))) {
                    item.SetTextStyle(i, num2 - i, TextStyle.HyperText);
                }
                i = num2;
                if (i == num) {
                    i++;
                }
            }
        }
        protected bool IsSpellDelimiter(char ch) {
            return ch <= ' ' || this.spellTable.ContainsKey(ch);
        }
        protected void DoCheckSpelling(StringItem item, int line, bool withUpdate) {
            string @string = item.String;
            if (@string != string.Empty) {
                bool flag = (this.state & NotifyState.Edit) != NotifyState.None && this.position.Y == line;
                this.spellSkipPt = (flag ? this.position : new Point(-1, -1));
                int num = 0;
                bool flag2 = false;
                int length = @string.Length;
                if (withUpdate) {
                    this.BeginUpdate(UpdateReason.Other);
                }
                try {
                    for (int i = 0; i < length; i++) {
                        bool flag3 = this.IsSpellDelimiter(@string[i]);
                        if (i == 0) {
                            flag2 = flag3;
                        }
                        if (flag2 != flag3) {
                            if (flag3) {
                                if (!flag || this.spellSkipPt.X <= num || this.spellSkipPt.X > i) {
                                    this.DoCheckSpelling(item, line, num, i, withUpdate);
                                }
                            }
                            flag2 = flag3;
                            num = i;
                        }
                    }
                    if (!flag2 && (!flag || this.spellSkipPt.X <= num || this.spellSkipPt.X > length)) {
                        this.DoCheckSpelling(item, line, num, length, withUpdate);
                    }
                } finally {
                    if (withUpdate) {
                        this.EndUpdate();
                    }
                }
            }
        }
        protected virtual void OnHighlightHyperTextChanged() {
            this.LexerChanged();
        }
        public virtual bool IsHyperText(string text) {
            bool flag = Circus.CodeEditor.TextSource.HyperText.IsHyperText(text);
            if (this.HyperText != null) {
                this.hyperTextArgs.Text = text;
                this.hyperTextArgs.IsHyperText = flag;
                this.HyperText(this, this.hyperTextArgs);
                flag = this.hyperTextArgs.IsHyperText;
            }
            return flag;
        }
   
        private void InitSpellTable() {
            if (this.spellTable == null) {
                this.spellTable = new Hashtable();
                this.UpdateSpellTable();
            }
        }
        private void UpdateSpellTable() {
            this.spellTable.Clear();
            char[] array = this.SpellDelimiters;
            for (int i = 0; i < array.Length; i++) {
                char c = array[i];
                this.spellTable.Add(c, c);
            }
        }
        private void DoParseBraces(StringItem item, int line) {
            this.bracesList.RemoveBraces(line);
            string @string = item.String;
            StringItemInfo[] textData = item.TextData;
            for (int i = 0; i < @string.Length; i++) {
                if (this.lexer == null || !this.lexer.Scheme.IsPlainText((int)(textData[i].Data - 1))) {
                    char value = @string[i];
                    int num = Array.IndexOf<char>(this.openBraces, value);
                    if (num >= 0) {
                        this.bracesList.AddBrace(line, i, num, true);
                    } else {
                        num = Array.IndexOf<char>(this.closingBraces, value);
                        if (num >= 0) {
                            this.bracesList.AddBrace(line, i, num, false);
                        }
                    }
                }
            }
        }
        protected virtual void OnCheckSpellingChanged() {
            this.InitSpellTable();
            this.LexerChanged();
        }
        protected virtual void OnSpellDelimitersChanged() {
            this.InitSpellTable();
            this.UpdateSpellTable();
            this.LexerChanged();
        }
        public virtual bool IsWordCorrect(string text) {
            return this.IsWordCorrect(text, default(StringItemInfo));
        }
        protected bool IsWordCorrect(string text, StringItemInfo colorStyle) {
            bool flag = true;
            if (this.WordSpell != null) {
                this.wordSpellArgs.Text = text;
                this.wordSpellArgs.Correct = flag;
                this.wordSpellArgs.ColorStyle = colorStyle;
                this.WordSpell(this, this.wordSpellArgs);
                flag = this.wordSpellArgs.Correct;
            }
            return flag;
        }

        private void StartBracesTimer() {
            this.EndBracesTimer();
            if (this.bracesTimer == null) {
                this.bracesTimer = new System.Windows.Forms.Timer();
                this.bracesTimer.Enabled = false;
                this.bracesTimer.Interval = EditConsts.DefaultBracesDelay;
                this.bracesTimer.Tick += new EventHandler(this.OnUnhighlightBraces);
            }
            this.bracesTimer.Enabled = true;
        }
        private void EndBracesTimer() {
            if (this.bracesTimer != null) {
                this.bracesTimer.Enabled = false;
            }
        }
        private void UpdateBraces(bool needUpdate) {
            this.UpdateBraces(needUpdate, -1, -1);
        }
        private void UpdateBraces(bool needUpdate, int first, int last) {
            this.UpdateBrace(this.openBrace, this.openBraceLen, true, needUpdate || (first >= 0 && this.openBrace.Y < first));
            this.UpdateBrace(this.closingBrace, this.closingBraceLen, true, needUpdate || (last >= 0 && this.closingBrace.Y > last));
        }
        private void UpdateTempBraces(bool value, bool needUpdate) {
            if (this.tempBraceRects != null) {
                Rectangle[] array = this.tempBraceRects;
                for (int i = 0; i < array.Length; i++) {
                    Rectangle rect = array[i];
                    this.SetTextStyle(rect, TextStyle.Brace, value, needUpdate);
                }
            }
        }
        private bool HighlightBraces(Point position, bool needUpdate, int first, int last) {
            Point point = this.openBrace;
            Point point2 = this.closingBrace;
            Point point3 = position;
            int len = this.openBraceLen;
            int len2 = this.closingBraceLen;
            this.openBrace = new Point(-1, -1);
            this.closingBrace = new Point(-1, -1);
            bool flag = false;
            bool flag2 = false;
            if (position.X > 0 && this.bracesList.FindBrace(new Point(position.X - 1, position.Y), out flag2) && !flag2) {
                point3.X--;
            } else {
                if (this.bracesList.FindBrace(position, out flag2) && flag2) {
                    point3.X++;
                }
            }
            int num = -1;
            int num2 = 1;
            int num3 = 1;
            if (this.FindOpenBrace(ref point3, ref num2, ref num)) {
                Point point4 = point3;
                point4.X++;
                if (this.FindClosingBrace(ref point4, ref num3, ref num)) {
                    if ((this.bracesOptions & BracesOptions.HighlightBounds) == BracesOptions.None || position.Equals(point3) || position.Equals(new Point(point4.X + 1, point4.Y))) {
                        this.openBrace = point3;
                        this.closingBrace = point4;
                        this.openBraceLen = num2;
                        this.closingBraceLen = num3;
                        flag = true;
                    }
                }
            }
            bool flag3 = this.openBrace != point || this.closingBrace != point2;
            if (flag3) {
                this.UpdateBrace(point, len, false, needUpdate);
                this.UpdateBrace(point2, len2, false, needUpdate);
                this.UpdateBraces(needUpdate, first, last);
            }
            if (flag && (this.bracesOptions & BracesOptions.TempHighlight) != BracesOptions.None) {
                this.StartBracesTimer();
            }
            return flag3;
        }
        private void UpdateBrace(Point point, int len, bool value, bool needUpdate) {
            this.SetTextStyle(point, len, TextStyle.Brace, value, needUpdate);
        }
        protected virtual bool FindClosingBrace(ref Point position, ref int len, ref int braceIndex) {
            return this.closingBraces != null && this.bracesList.FindClosingBrace(ref position, ref braceIndex, this.closingBraces.Length);
        }
        protected virtual bool FindOpenBrace(ref Point position, ref int len, ref int braceIndex) {
            return this.openBraces != null && this.bracesList.FindOpenBrace(ref position, ref braceIndex, this.openBraces.Length);
        }
        public virtual void TempUnhighlightBraces(bool needUpdate) {
            this.TempBraceRects = null;
            this.UpdateBraces(needUpdate);
        }
        protected virtual void HighlightBraces(bool needUpdate) {
            this.HighlightBraces(this.position, needUpdate, -1, -1);
        }
        public virtual void UnhighlightBraces(bool needUpdate) {
            this.UpdateBrace(this.openBrace, this.openBraceLen, false, needUpdate);
            this.UpdateBrace(this.closingBrace, this.closingBraceLen, false, needUpdate);
            this.openBrace = new Point(-1, -1);
            this.closingBrace = new Point(-1, -1);
            this.EndBracesTimer();
        }
        protected void OnUnhighlightBraces(object source, EventArgs e) {
            if (this.bracesOptions != BracesOptions.None) {
                this.UnhighlightBraces();
            }
            this.TempUnhighlightBraces();
        }
        protected virtual void OnBracesOptionsChanged() {
            this.LexerChanged();
            if ((this.bracesOptions & BracesOptions.TempHighlight) == BracesOptions.None) {
                this.UpdateTempBraces(false, true);
            }
            if ((this.bracesOptions & BracesOptions.Highlight) != BracesOptions.None) {
                this.HighlightBraces();
            }
        }
        protected virtual void OnOpenBracesChanged() {
            if (this.bracesOptions != BracesOptions.None) {
                this.LexerChanged();
            }
        }
        protected virtual void OnClosingBracesChanged() {
            if (this.bracesOptions != BracesOptions.None) {
                this.LexerChanged();
            }
        }

        public virtual bool FindClosingBrace(ref int x, ref int y) {
            Point point = new Point(x, y);
            bool result;
            if (this.FindClosingBrace(ref point)) {
                x = point.X;
                y = point.Y;
                result = true;
            } else {
                result = false;
            }
            return result;
        }
        public virtual bool FindClosingBrace(ref Point position) {
            int num = -1;
            int num2 = 1;
            return this.FindClosingBrace(ref position, ref num2, ref num);
        }
        public virtual bool FindOpenBrace(ref int x, ref int y) {
            Point point = new Point(x, y);
            bool result;
            if (this.FindOpenBrace(ref point)) {
                x = point.X;
                y = point.Y;
                result = true;
            } else {
                result = false;
            }
            return result;
        }
        public virtual bool FindOpenBrace(ref Point position) {
            int num = -1;
            int num2 = 1;
            return this.FindOpenBrace(ref position, ref num2, ref num);
        }
        public virtual void TempHighlightBraces(Rectangle[] rects) {
            this.TempBraceRects = rects;
        }
        public virtual void TempUnhighlightBraces() {
            this.TempBraceRects = null;
            this.UpdateBraces(true);
        }
        public virtual void HighlightBraces() {
            this.HighlightBraces(true);
        }
        public virtual void UnhighlightBraces() {
            this.UnhighlightBraces(true);
        }

        private void SyntaxParserChanged(EventArgs e) {
            SyntaxParserEventArgs syntaxParserEventArgs = e as SyntaxParserEventArgs;
            if (syntaxParserEventArgs != null) {
                this.OnTextParsed(syntaxParserEventArgs.Update, syntaxParserEventArgs.Rescan, syntaxParserEventArgs.First, syntaxParserEventArgs.Last);
            } else {
                this.OnTextParsed();
            }
        }
        private void LexerChanged() {
            this.StopParserThread(true);
            this.BeginUpdate(UpdateReason.Other);
            try {
                this.lastParsed = -1;
                this.state |= NotifyState.SyntaxChanged;
                this.UpdateParsed(0, this.lines.Count - 1);
                this.bracesList.Clear();
                this.UnhighlightSyntaxErrors(this.syntaxErrors, false);
                this.UnhighlightCodeSnippets(false);
            } finally {
                this.EndUpdate();
            }
        }
        protected void UpdateParsed(int fromIndex, int toIndex) {
            for (int i = fromIndex; i <= Math.Min(toIndex, this.lines.Count - 1); i++) {
                StringItem item = this.lines.GetItem(i);
                item.State &= ~ItemState.Parsed;
            }
        }
        protected virtual void StopParserThread(bool wait) {
            this.StopThread(this.reparseTextAction, wait);
            if (this.NeedReparseText()) {
                SyntaxParser syntaxParser = (SyntaxParser)this.Lexer;
                syntaxParser.StopParsing();
            }
        }
        private void UndefinedSectionChanged(int deltaX, int deltaY) {
            if (this.undefinedSections != null) {
                for (int i = 0; i < this.undefinedSections.Count; i++) {
                    Rectangle value = this.undefinedSections[i];
                    Point point = new Point(value.Left, value.Top);
                    Point point2 = new Point(value.Right, value.Bottom);
                    Range.UpdatePos(this.Position.X, this.Position.Y, deltaX, deltaY, ref point, false);
                    Range.UpdatePos(this.Position.X, this.Position.Y, deltaX, deltaY, ref point2, true);
                    value.Location = new Point(point.X, point.Y);
                    value.Size = new Size(point2.X - point.X, point2.Y - point.Y);
                    this.undefinedSections[i] = value;
                }
            }
        }
        private bool UndefinedSectionsDeleting(Rectangle rect) {
            bool result = false;
            if (this.undefinedSections != null) {
                for (int i = this.undefinedSections.Count - 1; i >= 0; i--) {
                    Rectangle rectangle = this.undefinedSections[i];
                    if (Range.InsideRange(new Point(rectangle.Left, rectangle.Top), rect) && Range.InsideRange(new Point(rectangle.Right, rectangle.Bottom), rect, true)) {
                        this.undefinedSections.RemoveAt(i);
                        result = true;
                    }
                }
            }
            return result;
        }
        private void UpdateUndefinedSections(bool value, bool needUpdate) {
            if (this.undefinedSections != null) {
                foreach (Rectangle current in this.undefinedSections) {
                    this.SetTextStyle(current, TextStyle.WhiteSpace, value, needUpdate);
                }
            }
        }
        public virtual void SetLastParsed(int index) {
            this.lastParsed = index;
            if (this.firstChanged >= 0 && index >= 0) {
                this.firstChanged = Math.Min(this.firstChanged, index);
            }
        }
        public virtual void ParseString(int index) {
            this.ParseStrings(index, index);
        }
        public virtual void ParseStrings(int first, int last) {
            if (this.NeedParse()) {
                int num = (first > 0 && first - 1 < this.lines.Count) ? this.lines.GetItem(first - 1).LexState : ((this.lexer != null) ? this.lexer.DefaultState : 0);
                first = Math.Max(first, 0);
                last = Math.Min(last, this.lines.Count - 1);
                for (int i = first; i <= last; i++) {
                    StringItem item = this.lines.GetItem(i);
                    if ((byte)(item.State & ItemState.Parsed) == 0 || item.PrevLexState != num) {
                        item.PrevLexState = num;
                        num = this.ParseText(num, item, i, false);
                        item.LexState = num;
                        StringItem expr_BA = item;
                        expr_BA.State |= ItemState.Parsed;
                    } else {
                        num = item.LexState;
                    }
                }
            }
        }
        public virtual void ParseToString(int index) {
            if (this.lastParsed < index) {
                int first = this.lastParsed;
                this.ParseStrings(first, index);
                this.lastParsed = index + 1;
                if (this.bracesOptions != BracesOptions.None) {
                    if (!this.HighlightBraces(this.Position, false, first, index)) {
                        this.UpdateBraces(false);
                    }
                }
                if (this.tempBraceRects != null) {
                    this.UpdateTempBraces(true, false);
                }
                if (this.undefinedSections != null) {
                    this.UpdateUndefinedSections(true, false);
                }
                this.InvalidateSyntaxErrors();
                this.HighlightCodeSnippets(false);
            }
        }
        public virtual bool NeedParse() {
            return this.lexer != null || this.checkSpelling || this.highlightHyperText || this.bracesOptions != BracesOptions.None;
        }
        public virtual bool ProcessAutoComplete(out string code) {
            code = string.Empty;
            return this.NeedAutoComplete() && ((SyntaxParser)this.lexer).ProcessAutoComplete(this.Lines[this.prevPosition.Y], this.prevPosition, out code);
        }

        public virtual void FormatText(bool immediate, bool notify) {
            this.needFormatting = false;
            if (notify) {
                this.EndFmtTimer(false);
            }
            if (this.NeedReparseText()) {
                SyntaxParser syntaxParser = (SyntaxParser)this.Lexer;
                if (!immediate && this.NeedWorkInThread() && !this.NeedFormatTextOnLineChange()) {
                    syntaxParser.Prepare(this.fileName, this.Lines, null, false);
                    this.StartThread(this.reparseTextAction, this.reparseTextStart, this.reparseTextEnd, this.reparseTextStop);
                } else {
                    syntaxParser.Prepare(this.fileName, this.Lines, null, false);
                    syntaxParser.ReparseText(false, this.firstUpdated, this.lastUpdated);
                    if (notify && (syntaxParser.Options & SyntaxOptions.NotifyOnParse) == SyntaxOptions.None) {
                        this.OnTextParsed();
                    }
                }
            }
        }
        public virtual void FormatText() {
            this.FormatText(true, true);
        }
        public virtual bool NeedIndentText() {
            SyntaxOptions syntaxOptions = (this.lexer is SyntaxParser) ? ((SyntaxParser)this.lexer).Options : SyntaxOptions.None;
            return (syntaxOptions & SyntaxOptions.SmartIndent) != SyntaxOptions.None;
        }
        public virtual bool NeedFormatText() {
            SyntaxOptions syntaxOptions = (this.lexer is SyntaxParser) ? ((SyntaxParser)this.lexer).Options : SyntaxOptions.None;
            return (syntaxOptions & SyntaxOptions.SmartIndent) != SyntaxOptions.None || (syntaxOptions & SyntaxOptions.FormatSpaces) != SyntaxOptions.None || (syntaxOptions & SyntaxOptions.FormatCase) != SyntaxOptions.None;
        }
        public virtual bool NeedOutlineText() {
            return this.lexer is SyntaxParser && (((SyntaxParser)this.lexer).Options & SyntaxOptions.Outline) != SyntaxOptions.None;
        }
        public virtual bool NeedReparseText() {
            return this.lexer is SyntaxParser && ((SyntaxParser)this.lexer).Options != SyntaxOptions.None;
        }
        public virtual bool NeedWorkInThread() {
            return ((SyntaxParser)this.lexer).SupportsThread;
        }
        public virtual bool NeedAutoComplete() {
            return this.lexer is SyntaxParser && (((SyntaxParser)this.lexer).Options & SyntaxOptions.AutoComplete) != SyntaxOptions.None;
        }
        public virtual bool NeedReparseTextOnLineChange() {
            return this.lexer is SyntaxParser && (((SyntaxParser)this.lexer).Options & SyntaxOptions.ReparseOnLineChange) != SyntaxOptions.None;
        }
        public virtual bool NeedFormatTextOnLineChange() {
            return this.NeedReparseTextOnLineChange() && ((((SyntaxParser)this.lexer).Options & SyntaxOptions.FormatCase) != SyntaxOptions.None || (((SyntaxParser)this.lexer).Options & SyntaxOptions.FormatSpaces) != SyntaxOptions.None);
        }
        public virtual bool NeedCodeCompletion() {
            return this.lexer is SyntaxParser && (((SyntaxParser)this.lexer).Options & SyntaxOptions.CodeCompletion) != SyntaxOptions.None;
        }
        public virtual bool NeedCodeCompletionTabs(CodeCompletionType completionType) {
            return this.lexer is SyntaxParser && (((SyntaxParser)this.lexer).Options & SyntaxOptions.CodeCompletionTabs) != SyntaxOptions.None && ((SyntaxParser)this.lexer).SupportsCodeCompletionFiltering(completionType);
        }
        public virtual bool NeedSyntaxErrors() {
            return this.lexer is SyntaxParser && (((SyntaxParser)this.lexer).Options & SyntaxOptions.SyntaxErrors) != SyntaxOptions.None;
        }
        public virtual bool NeedQuickInfoTips() {
            return this.lexer is SyntaxParser && (((SyntaxParser)this.lexer).Options & SyntaxOptions.QuickInfoTips) != SyntaxOptions.None;
        }
        private void StartFmtTimer(bool modified, bool lineChanged) {
            this.needFormatting |= modified;
            if (modified) {
                this.EndFmtTimer(true);
                if (this.NeedReparseText() && ((this.state & NotifyState.StringsChanged) != NotifyState.None || (this.state & NotifyState.SyntaxChanged) != NotifyState.None || !this.NeedReparseTextOnLineChange())) {
                    if (this.firstUpdated == -1) {
                        this.firstUpdated = this.firstChanged;
                    } else {
                        this.firstUpdated = Math.Min(this.firstUpdated, this.firstChanged);
                    }
                    this.lastUpdated = Math.Max(this.lastUpdated, this.lastChanged);
                    if (this.fmtTimer == null) {
                        this.fmtTimer = new System.Windows.Forms.Timer();
                        this.fmtTimer.Enabled = false;
                        this.fmtTimer.Tick += new EventHandler(this.OnFormatting);
                    }
                    this.fmtTimer.Interval = (this.lexer as SyntaxParser).ParseInterval;
                    this.fmtTimer.Enabled = true;
                }
            }
            if (lineChanged && this.needFormatting && this.NeedReparseTextOnLineChange()) {
                this.EndFmtTimer(true);
                this.FormatText(false, true);
            }
        }
        private void EndFmtTimer(bool cancel) {
            if (this.fmtTimer != null) {
                this.fmtTimer.Enabled = false;
            }
            if (cancel) {
                this.StopParserThread(false);
            }
        }
        private void ReparseTextAction() {
            if (this.lexer is SyntaxParser) {
                SyntaxParser syntaxParser = (SyntaxParser)this.Lexer;
                syntaxParser.ReparseText(true);
            }
        }
        private void ReparseTextStart() {
            if (this.lexer is SyntaxParser) {
                ((SyntaxParser)this.lexer).Prepare(this.fileName, this.Lines, null, true);
            }
        }
        private void ReparseTextEnd() {
            if (this.lexer is SyntaxParser) {
                ((SyntaxParser)this.lexer).FinishParsing();
                this.OnTextParsed();
            }
        }
        private void ReparseTextStop() {
            if (this.lexer is SyntaxParser) {
                ((SyntaxParser)this.lexer).StopParsing();
            }
        }
        protected virtual void OnTextParsed() {
            this.OnTextParsed(true, false, 0, int.MaxValue);
        }
        protected virtual void OnTextParsed(bool update, bool rescan, int first, int last) {
            this.BeginUpdate(UpdateReason.Other);
            try {
                if (rescan) {
                    first = Math.Max(first, 0);
                    last = Math.Min(last, this.Lines.Count - 1);
                    this.LinesChanged(first, last, false);
                    this.UpdateParsed(first, last);
                    this.SetLastParsed(first);
                    this.state |= (NotifyState.BlockChanged | NotifyState.TextParsed);
                }
                if (update) {
                    if (this.NeedSyntaxErrors()) {
                        this.HighlightSyntaxErrors();
                    }
                    SyntaxParser syntaxParser = this.lexer as SyntaxParser;
                    if (syntaxParser != null && (syntaxParser.Options & SyntaxOptions.EvaluateConditionals) != SyntaxOptions.None && syntaxParser.ExpressionEvaluator != null) {
                        this.UndefinedSections = syntaxParser.ExpressionEvaluator.UndefinedSections;
                    } else {
                        this.UndefinedSections = null;
                    }
                    this.state |= (NotifyState.BlockChanged | NotifyState.Outline | NotifyState.TextParsed);
                }
                this.firstUpdated = -1;
                this.lastUpdated = -1;
            } finally {
                this.EndUpdate();
            }
        }
        protected void SetTextStyle(Rectangle rect, TextStyle style, bool setFlag, bool needUpdate) {
            for (int i = rect.Top; i <= rect.Bottom; i++) {
                int num;
                int num2;
                if (i == rect.Top) {
                    if (i == rect.Bottom) {
                        num = rect.Left;
                        num2 = rect.Right;
                    } else {
                        num = rect.Left;
                        num2 = int.MaxValue;
                    }
                } else {
                    if (i == rect.Bottom) {
                        num = 0;
                        num2 = rect.Right;
                    } else {
                        num = 0;
                        num2 = int.MaxValue;
                    }
                }
                this.SetTextStyle(new Point(num, i), (num2 == int.MaxValue) ? num2 : (num2 - num), style, setFlag, needUpdate);
            }
        }
        protected void SetTextStyle(Point pos, int len, TextStyle style, bool setFlag, bool needUpdate) {
            if (pos.Y >= 0) {
                StringItem item = this.Lines.GetItem(pos.Y);
                if (item != null) {
                    if (needUpdate) {
                        this.BeginUpdate(UpdateReason.Other);
                    }
                    try {
                        int num = item.TextData.Length;
                        if (pos.X >= 0 && pos.X < num) {
                            len = Math.Min(len, num - pos.X);
                            if (len > 0) {
                                if (setFlag) {
                                    item.SetTextStyle(pos.X, len, style);
                                } else {
                                    item.ClearTextStyle(pos.X, len, style);
                                }
                            }
                        }
                        this.LinesChanged(pos.Y, pos.Y);
                        this.state |= NotifyState.BlockChanged;
                    } finally {
                        if (needUpdate) {
                            this.EndUpdate();
                        }
                    }
                }
            }
        }
        protected void OnFormatting(object source, EventArgs e) {
            this.EndFmtTimer(false);
            if (this.NeedReparseText()) {
                this.FormatText(false, true);
            }
        }

        protected virtual void OnLinesChanged() {
        }
        protected virtual void OnTextChanged() {
        }
        protected virtual void OnActiveEditChanged() {
        }
        protected virtual void OnLineStylesChanged() {
        }
        protected virtual void OnBookmarksChanged() {
        }
        protected Point IncPosition(Point position, int len) {
            int num = this.lines.Count;
            int num2 = 0;
            Point result = position;
            while (len > 0) {
                if (position.Y < num) {
                    num2 = ((result.Y < num) ? this.lines.GetLength(result.Y) : 0);
                    if (result.Y == position.Y) {
                        num2 -= position.X;
                    }
                    num2 = Math.Max(num2, 0);
                }
                if (len <= num2) {
                    result.X = len;
                    if (position.Y == result.Y) {
                        result.X += position.X;
                    }
                    break;
                }
                result.Y++;
                len -= num2 + 2;
                if (len <= 0 && position.Y != result.Y) {
                    result.X = Math.Max(len, 0);
                }
            }
            return result;
        }
        public virtual int TextPointToAbsolutePosition(Point position) {
            return this.lines.TextPointToAbsolutePosition(position);
        }
        public virtual Point AbsolutePositionToTextPoint(int position) {
            return this.lines.AbsolutePositionToTextPoint(position);
        }
        public virtual int GetCharIndexFromPosition(Point position) {
            return this.lines.TextPointToAbsolutePosition(position);
        }
        public virtual Point GetPositionFromCharIndex(int charIndex) {
            return this.lines.AbsolutePositionToTextPoint(charIndex);
        }
        public virtual StringItem CreateStringItem(string s) {
            return new StringItem(s);
        }

        protected virtual void StartThread(object obj) {
            if (this.thread == null) {
                this.thread = new TextSource.BackgroundThread(this);
            }
            this.thread.Start(obj as ThreadProcsEventArgs);
        }
        public virtual void StartThread(ThreadProc action, ThreadProc start, ThreadProc end, ThreadProc stop) {
            this.StartThread(new ThreadProcsEventArgs(action, start, end, stop));
        }
        public virtual void StopThread(ThreadProc action, bool wait) {
            if (this.thread != null) {
                this.thread.Stop(action, wait);
            }
        }
        protected override void Dispose(bool disposing) {
            if (disposing) {
                this.activeEdit = null;
                this.StopParserThread(true);
                this.lines.RemoveNotifier(this);
                if (this.lexer != null) {
                    this.lexer.RemoveNotifier(this);
                    this.lexer = null;
                }
                this.ClearUndo();
                this.ClearRedo();
                if (this.fmtTimer != null) {
                    this.fmtTimer.Dispose();
                    this.fmtTimer = null;
                }
                if (this.bracesTimer != null) {
                    this.bracesTimer.Dispose();
                    this.bracesTimer = null;
                }
                BookMarkManager.Unregister(this);
            }
            base.Dispose(disposing);
        }
    }
}
